Only 20min timelapse because we concluded that we wont be able to
decouple photobleaching from proteasomal decay
this RMD is to generate the df for decay rate estimation for the DMSO
control
library(data.table)
library(tidyverse)
library(reshape2)
library(gganimate)
library(ggridges)
library(ggpubr)
source("~/R-scripts/R_functions/master-2-3-22.R")
#getting the information for imaris files ##files to read from
Imaris
FilesToRead <- c("C0_Area",
"C0_Ellipsoid_Axis_Length_B",
"C0_Ellipsoid_Axis_Length_C",
"C0_Intensity_Center_Ch=3",
"C0_Intensity_Mean_Ch=3",
"C0_Intensity_Median_Ch=3",
"C0_Intensity_Sum_Ch=3",
"C0_Number_of_Voxels",
"C0_Number_of_Triangles",
"C0_Sphericity",
"C0_Volume.csv",
"C0_Position.csv" )
##actual reading and making them into df
####MG131
#Getting the list of all the samples in the experiment
gfp_imaris <- dir("~/Imaris-data/2022/pup1_rfp/7-20-22-pup1/stable/imaris/gfp", full.names = TRUE)
#getting the information for imageJ image info files
#getting all the image info txt for all the images in the experiment.
list.image.info <- list.files("~/Imaris-data/2022/pup1_rfp/7-20-22-pup1/stable/image_info_imageJ" , full.names = TRUE)
#Extracting information from the imageJ csv into a df with actual time differences between each images
real.time.interval.df <- get.image.info.OnlyGFP(list.image.info = list.image.info)
#Extracting information from the imaris csv into a df with information on area, time, gfp intensity, mcherry intensity, (mean, median and sum), volume, trackID and IDs
list.of.files.gfp <- get.imaris.info.onlyGFP( dir.names = gfp_imaris,
files_to_read = FilesToRead ,
real.time.interval.df = real.time.interval.df)
list.of.files.gfp$`20min` %>%
split(.$field)
#Assigning the sample by to each field. There are two fields of
autofluorescecne in this experiment. The neg.singal stands for the
autofluorescence sample.
list.of.files.gfp[["20min"]] <- list.of.files.gfp[["20min"]] %>%
mutate(sample = ifelse(exp.field %in% c("20min_s1", "20min_s2"), "neg.signal", "pos.signal"))
#getting the imaris info of DAPI and pup1-rfp ##files to read (these
will have rfp and dapi) ##Use the cells_surface data from Imaris #files
to read
#reading the cell surface imaris files
# dapi_pup1_imaris_cells <- dir("~/Imaris-data/2022/proteasome_inhibition/2-23-22-PI/1uM/imaris/surface/cells", full.names = TRUE)
#
# list.of.files.dapi.pup1 <- get.imaris.info.dapi_pup1(dir.names = dapi_pup1_imaris_cells,
# files_to_read = FilesToReadDAPIRFP)
#
# unique(list.of.files.dapi.pup1$timepoint)
#getting the pup1-rfp puncta info ##use the pup1_surface info from
Imaris
FilesToReadDAPIRFP <- c("C0_Area",
"C0_BoundingBoxOO_Length_B",
"C0_BoundingBoxOO_Length_C",
"C0_Ellipsoid_Axis_Length_B",
"C0_Ellipsoid_Axis_Length_C",
"C0_Intensity_Center_Ch=4",
"C0_Intensity_Mean_Ch=4",
"C0_Intensity_Median_Ch=4",
"C0_Intensity_Sum_Ch=4",
"C0_Intensity_Center_Ch=5",
"C0_Intensity_Mean_Ch=5",
"C0_Intensity_Median_Ch=5",
"C0_Intensity_Sum_Ch=5",
"C0_Number_of_Voxels",
"C0_Number_of_Triangles",
"C0_Sphericity",
"C0_Volume.csv",
"C0_Position_X.csv",
"C0_Position_Y.csv",
"C0_Intensity_Max_Ch=6",
"C0_Intensity_Center_Ch=6")
#first get the info of the cell surface then match each cell surface
with the pup1 puncta. do not include the MRG cells as they have no
pup1-rfp puncta mask
dapi_pup1_imaris_cells <- dir("~/Imaris-data/2022/pup1_rfp/7-20-22-pup1/stable/imaris/surface/cells", full.names = TRUE)
list.of.files.dapi.pup1 <- get.imaris.info.dapi_pup1.surface(dir.names = dapi_pup1_imaris_cells, files_to_read = FilesToReadDAPIRFP) #updated this function to not include trackIDs
list.of.files.dapi.pup1 <- list.of.files.dapi.pup1 %>%
mutate(timepoint = ifelse(timepoint == 2,31,timepoint))
list.of.files.dapi.pup1 %>% split(.$timepoint)
#Getting the pup1 puncta surface info
pup1_surface_imaris <- dir("~/Imaris-data/2022/pup1_rfp/7-20-22-pup1/stable/imaris/surface/pup1", full.names = TRUE)
pup1_puncta <- get.imaris.info.dapi_pup1.surface(dir.names = pup1_surface_imaris[3:8],
files_to_read = FilesToReadDAPIRFP)
pup1_puncta <- pup1_puncta %>%
mutate(timepoint = ifelse(timepoint == 2,31,timepoint))
pup1_puncta %>% split(.$timepoint)
#combine the cell surface info with the pup1 puncta info.
#this should have 11159 no. of cells
pup1.dapi.cell.puncta <- list.of.files.dapi.pup1 %>% #df with entire cell segmented
select(
area,
pos.x,
pos.y,
timepoint,
all.mask.int.max,
all.mask.int.center,
rfp.int.mean,
rfp.int.median,
rfp.int.sum,
dapi.int.mean,
dapi.int.median,
dapi.int.sum,
experiment,
field
) %>%
left_join(
.,
pup1_puncta %>% #df with the pup1 puncta segmented
select(
rfp.int.center,
rfp.int.mean,
rfp.int.median,
rfp.int.sum,
dapi.int.mean,
dapi.int.sum,
dapi.int.median,
all.mask.int.max,
all.mask.int.center,
area,
timepoint,
experiment,
field,
no.of.voxels
) %>% rename("area.puncta" = "area",
"rfp.center.puncta" = "rfp.int.center",
"rfp.mean.puncta" = "rfp.int.mean",
"rfp.sum.puncta" = "rfp.int.sum",
"rfp.median.puncta" = "rfp.int.median",
"dapi.mean.puncta" = "dapi.int.mean",
"dapi.sum.puncta" = "dapi.int.sum",
"dapi.median.puncta" = "dapi.int.median",
"no.of.voxels.puncta" = "no.of.voxels"),
by = c("all.mask.int.max" ,
"experiment" ,
"field" ,
"timepoint" ,
"all.mask.int.center")
)
#this has 6514 cells. some cells have multiple puncta. maybe just drop the cells.
#combine the cell surface + pup1 puncta info of the pup1 expressing
cells with all the cell surface information. There will be NAs in the
columns with puncta in their names for the neg cells
# pup1.dapi.all <- list.of.files.dapi.pup1 %>%
# left_join(.,pup1.dapi.cell.puncta %>%
# select(.,area,
# pos.x,
# pos.y,
# timepoint,
# experiment,
# field,
# rfp.center.puncta, rfp.mean.puncta, rfp.median.puncta, rfp.sum.puncta,
# dapi.mean.puncta,dapi.sum.puncta, dapi.median.puncta,
# area.puncta, no.of.voxels.puncta),
# by = c("area","pos.x","pos.y","timepoint", "experiment", "field"))
#
# pup1.dapi.all
#dont need to do this.
Combining the GFP intensities with the rfp puncta info at t = 1
cell_atributes <- list.of.files.gfp$`20min` %>%
filter(timepoint %in% c(1,31)) %>%
left_join(.,pup1.dapi.cell.puncta %>% select(-all.mask.int.max,
-all.mask.int.center) ,
by = c("area",
"timepoint",
"pos.x",
"pos.y",
"experiment",
"field"))
cell_atributes %>%
# filter(unique.trackID == "1000001774_20min_s3")
dplyr::group_by(field, unique.trackID, timepoint) %>%
dplyr::summarise(n = dplyr::n(), .groups = "drop") %>%
dplyr::filter(n > 1L)
#6440 cells. There are 6 cells with multiple pup1 puncta. maybe drop these cells just for simplicity purposes.
#Background subtraction
#background info files for gfp and mcherry and DAPI: the background folder has two directories: gfp bg and mcherry+dapi bg
bg <- dir(path = "~/Imaris-data/2022/pup1_rfp/7-20-22-pup1/stable/background" , full.names = TRUE)
#Get the information for the background intensity for every image for
#rfp and DAPI
rfp.dapi.bg.means <- bg.intensity.rfp.dapi(bg.files = list.files(bg[1] , full.names = TRUE))
rfp.dapi.bg.means
$`20min`
#for GFP
gfp.bg.mean <- bg.intensity.gfp(bg.files = list.files(bg[2] , full.names = TRUE))
gfp.bg.mean$`20min` %>% arrange(field,timepoint)
#gfp background for s4, s5 and s6 samples:
#actually subtract the background intensity from the gfp and mcherry
intensity of the cells
#first fun. sub.bg.intensity subtracts the bg intensity from each cell.
gfp.bg.sub <- sub.bg.intensity.gfp(list.of.files = list.of.files.gfp,
bg.means = gfp.bg.mean$`20min` )
gfp.bg.sub
$`20min`
rfp.dapi.bg.sub <- sub.bg.intensity.dapi.rfp(list.of.files = cell_atributes,
bg.means = rfp.dapi.bg.means$`20min` )
gfp.bg.sub$`20min` %>%
filter(gfp.mean.bg.sub > 0,
) %>%
group_by(field, timepoint) %>%
tally()
rfp.dapi.bg.sub$`20min` %>% split(.$field)
$s1
$s2
$s3
$s4
$s5
$s6
$s7
$s8
NA
#combine the background subtracted gfp dataframe with the bg
subtracted rfp/dapi total and puncta dfs
gfp.rfp.dapi.bg.sub <- gfp.bg.sub$`20min` %>%
filter(timepoint %in% c(1,31)) %>%
select(unique.trackID,
gfp.mean.bg.sub,
gfp.sum.bg.sub,
avg.gfp.bg,
area,
pos.x,
pos.y) %>%
left_join(.,rfp.dapi.bg.sub$`20min`, by = c("unique.trackID", "area","pos.x","pos.y")) %>% split(.$experiment)
#filtering cells which have negative background subtracted
intensities
#Uniqe trackIDs of cells above the background int for gfp, dapi and rfp
#this function results in a list of two dfs. the 1st df = uniquetrackIDs with the experiment they're from.
listOfUniqtrackID_gfpfiltereddf <- trackID.abv.zero.gfp.rfp.dapi(
bg_subtracted_dftp1 = gfp.rfp.dapi.bg.sub,
list_gfp_all_tps = gfp.bg.sub)
#the df with gfp intensities for all timepoints which is filtered for cells gfp.mean.bg.sub > 0
list.of.files.bg.sub.above.0.gfp <- listOfUniqtrackID_gfpfiltereddf[[2]] %>%
split(.$experiment)
#removing cells with negative background subtracted intensities from
the dataframe with the cell info from timepoint 1 and the last
timepoint
gfp_rfp_dapi_bgsubAbvZero_tp1 <- listOfUniqtrackID_gfpfiltereddf[[1]] %>%
left_join(.,bind_rows(gfp.rfp.dapi.bg.sub) , by = c("unique.trackID", "experiment"))
gfp_rfp_dapi_bgsubAbvZero_tp1 %>%
group_by(timepoint, exp.field) %>%
tally()
list.of.files.bg.sub.above.0.gfp$`20min`%>%
group_by(timepoint, exp.field) %>% tally()
#s3, s4, s5, s6, s7 and s8 need to fix the background subtraction
#density plot of the DAPI staining. Higher DAPI staining == dead
cells
#at the first timepoint
gfp_rfp_dapi_bgsubAbvZero_tp1 %>%
ggplot(.,aes(x = dapi.mean.bg.sub, color = as.factor(timepoint)))+
geom_density(aes(y=..scaled..))+
facet_wrap(~field, scales = "free_x")+
scale_x_log10()+
theme_pubr(x.text.angle = 45)

#correlation of the dapi staining at timepint 1 and the last timepoint
# gfp_rfp_dapi_bgsubAbvZero_tp1 %>%
# select(dapi.mean.bg.sub, timepoint, field, unique.trackID) %>%
# filter(!(unique.trackID == "1000000259_20min_s8")) %>%
# pivot_wider(values_from = dapi.mean.bg.sub, names_from = timepoint) %>%
# ggplot(.,aes(x = `1`, y = `31`))+
# geom_point()+
# facet_wrap(~field, scales = "free_x")+
# theme_pubr(x.text.angle = 45)
#the above code did not work because there are duplicate values for a given cell ID.
#to find the duplicates
gfp_rfp_dapi_bgsubAbvZero_tp1 %>%
select(dapi.mean.bg.sub, timepoint, field, unique.trackID) %>%
dplyr::group_by(field, unique.trackID, timepoint) %>%
dplyr::summarise(n = dplyr::n(), .groups = "drop") %>%
dplyr::filter(n > 1L)
#remove the duplicates and look at how dapi staining is changing from timepoint 1 to tp 31:
#correlation of the dapi staining at timepint 1 and the last timepoint
gfp_rfp_dapi_bgsubAbvZero_tp1 %>%
select(dapi.mean.bg.sub, timepoint, field, unique.trackID) %>%
filter(!(unique.trackID == "1000002071_20min_s8")) %>%
pivot_wider(values_from = dapi.mean.bg.sub, names_from = timepoint) %>%
ggplot(.,aes(x = `1`, y = `31`))+
geom_point()+
facet_wrap(~field, scales = "free_x")+
theme_pubr(x.text.angle = 45)
Warning: Values from `dapi.mean.bg.sub` are not uniquely identified; output will contain list-cols.
* Use `values_fn = list` to suppress this warning.
* Use `values_fn = {summary_fun}` to summarise duplicates.
* Use the following dplyr code to identify duplicates.
{data} %>%
dplyr::group_by(field, unique.trackID, timepoint) %>%
dplyr::summarise(n = dplyr::n(), .groups = "drop") %>%
dplyr::filter(n > 1L)
Error: Discrete value supplied to continuous scale

#get the threshold of dapi above which the cells will be deemed
dead!!

#removing cells with dapi intensity greater than the dapi threshold
set
#getting the IDs of the cells remaining after removing the cells with higher than threshold dapi intensity. use this to filter cells from the df with mcherry and gfp timelapse information
#will remove dead cells from the first timepoint
dapi.filtered.cellsTrackID <- bind_rows(deadcell_temp_df) %>%
filter(timepoint %in% c(1,31)) %>%
left_join(.,deadCell_boundry, by = "exp.field") %>%
filter(dapi.mean.bg.sub < dapi.threshold) %>% pull(unique.trackID)
#df with fluorescent intensities of gfp, rfp and dapi for live cells at tp =1 ant tp = 31.
liveCellsRFP.DAPI.GFP <- gfp_rfp_dapi_bgsubAbvZero_tp1 %>%
left_join(.,deadCell_boundry, by = "exp.field") %>%
filter(dapi.mean.bg.sub < dapi.threshold)
#df with dead cells removed this df has gfp intensities for all the timepoint which are filtered for dead cells
new.gfpLiveCells <- bind_rows(list.of.files.bg.sub.above.0.gfp) %>%
filter(unique.trackID %in% liveCellsRFP.DAPI.GFP$unique.trackID)
#saving the dataframe with the background subtracted, dead cells
filtered intensities of gfps from the autofluor cells (MRG) and the gfp
positive cells.
looking at the distribution of rfp and gfp in the live cells

#plotting line plots raw without any AF filtering
bind_rows(new.gfpLiveCells)%>%
# filter(field %in% c("s7","s8")) %>%
ggplot(.,aes(timepoint, gfp.mean.bg.sub, group = unique.trackID ,color = sample))+
geom_line(alpha = 0.2)+
facet_wrap(~field, scales = "free_y")

# ggsave(filename="ln-mrg_vs_gfp.png", plot= last_plot() , path = "~/plots/7-2-20/plots_thesis_com_meet-2020/" , width = 13 , height = 8, bg = "transparent")
new.gfpLiveCells %>%
ggplot(.,aes(real.time.gfp, gfp.mean.bg.sub, group = unique.trackID ,color = sample))+
geom_line(alpha = 0.2)+
facet_wrap(~field, scales = "free_y")

# annotation_logticks()
Fix background for s1 and s8: fixed background intensities of s1, s3,
4 till s8.
#Filtering cells based on autofluorescence
##getting the autofluorescence threshold for gfp and mcherry

#filtering based on pup1-rfp expression ##filtering cells which are
above the gfp and rfp threshold In the
filter.cells.below.autofluor.31tp.gfpV2() function, the function looks
for the column named “threshold” and I need to decide which column will
be threshold based on the overlap of the neg and positive cells. This is
because there are cells which become dead/become in focus as you keep
taking images which might suddenly increase the 95th quantile intensity
of the negative cells.
#get a filtered df of cells passing the gfp threshold set above
#this function below first removes cells with pup1-rfp less than the threshold set.
#Then it removes the cells with less than AF threshold set at tp =1
#After that it subtracts the af value from every cell for every timepoint, and if the subtracted value is less than 1 it makes it NA.
cells.filtered.df.31tp <- filter.cells.below.autofluor.31tp.gfpV2(
df_rfp_dapi_gfp = liveCellsRFP.DAPI.GFP,
rfp_min_int = rfp.min.int %>% rename("quant_95" = "threshold_95",
"threshold_95" = "pup1_threshold"),
gfp_live_cells_list = new.gfpLiveCells %>% split(.$experiment),
gfp_min_int = gfp.min.int %>%
mutate(threshold = threshold_95 )
)
filtered.df.new.wo.af.31tp <- cells.filtered.df.31tp$filtered.df.new %>%
bind_rows() %>%
filter(sample == "pos.signal") %>%
split(.$experiment)
unique(filtered.df.new.wo.af.31tp$`20min`$timepoint)
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
remove the first two blurry images from s7
# filtered.df.new.wo.af.31tp$`20min` <- filtered.df.new.wo.af.31tp$`20min` %>% filter(field == "s7")
# filter(!(field == "s7" & timepoint %in% c(1,2)))
#making df for bulk regression
###This function creats the df for fitting the 24 models
# list.df.model <- df.model(filtered.df.new = filtered.df.new.wo.af)
df.model.31tp.gfp <- df.model.gfp(filtered.df.new = filtered.df.new.wo.af.31tp)
df.model.31tp.gfp
####This function cleans up the df where you subtract the t=0 intensity with all the other intensities for gfp
final.data.31tp.gfp <- clean.df.modeling.gfp(data.gfp = df.model.31tp.gfp)
On 1/28/21 talked to premal about filtering: 1. Remove cells which
have positive delta Intensity more than 2 times
#getting IDs of cells which have positive intensity values for less than 2 timepoints
ids.int.2 <- final.data.31tp.gfp %>%
group_by(unique.trackID) %>%
tally(ln.gfp.dif > 0) %>%
filter(n<2) %>% #keep cells which have less than two positive intensity values
pull(unique.trackID)
#filtering cells which have trackID in the above vector
#gfp
temp.posIntBlw2.gfp <- final.data.31tp.gfp %>%
filter(unique.trackID %in% ids.int.2)
df_for_MechanisticModel <- temp.posIntBlw2.gfp %>%
left_join(
.,
bind_rows(filtered.df.new.wo.af.31tp) ,
by = c(
"unique.trackID",
"timepoint" ,
"experiment" ,
"gfp.mean.bg.af.sub.new" ,
"exp.field"
)
)
#save this dataframe for half life estimation
#saving the data
#SAVING THE DATAFRAME WHICH HAS ALL THE BACKGROUND INT, AUTOFLUOR
INTENSITY (AT THE INTERSECTION, THE 80TH AND THE 95TH QUANTILE OF MRG
AUTO GFP INTENSITY)

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQotLS0KdGl0bGU6ICI3LTIwLTIyIHN0YWJsZS1nZnAgcHVwMS1yZnAgZGVjYXkiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCgpPbmx5IDIwbWluIHRpbWVsYXBzZSBiZWNhdXNlIHdlIGNvbmNsdWRlZCB0aGF0IHdlIHdvbnQgYmUgYWJsZSB0byBkZWNvdXBsZSBwaG90b2JsZWFjaGluZyBmcm9tIHByb3RlYXNvbWFsIGRlY2F5Cgp0aGlzIFJNRCBpcyB0byBnZW5lcmF0ZSB0aGUgZGYgZm9yIGRlY2F5IHJhdGUgZXN0aW1hdGlvbiBmb3IgdGhlIERNU08gY29udHJvbAoKYGBge3J9CmxpYnJhcnkoZGF0YS50YWJsZSkKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkocmVzaGFwZTIpCmxpYnJhcnkoZ2dhbmltYXRlKQpsaWJyYXJ5KGdncmlkZ2VzKQpsaWJyYXJ5KGdncHVicikKYGBgCgpgYGB7cn0Kc291cmNlKCJ+L1Itc2NyaXB0cy9SX2Z1bmN0aW9ucy9tYXN0ZXItMi0zLTIyLlIiKQpgYGAKCiNnZXR0aW5nIHRoZSBpbmZvcm1hdGlvbiBmb3IgaW1hcmlzIGZpbGVzCiMjZmlsZXMgdG8gcmVhZCBmcm9tIEltYXJpcwpgYGB7cn0KRmlsZXNUb1JlYWQgPC0gYygiQzBfQXJlYSIsIAogICAgICAgICAgICAiQzBfRWxsaXBzb2lkX0F4aXNfTGVuZ3RoX0IiLAogICAgICAgICAgICAiQzBfRWxsaXBzb2lkX0F4aXNfTGVuZ3RoX0MiLAogICAgICAgICAgICAiQzBfSW50ZW5zaXR5X0NlbnRlcl9DaD0zIiwKICAgICAgICAgICAgIkMwX0ludGVuc2l0eV9NZWFuX0NoPTMiLCAKICAgICAgICAgICAgIkMwX0ludGVuc2l0eV9NZWRpYW5fQ2g9MyIsCiAgICAgICAgICAgICJDMF9JbnRlbnNpdHlfU3VtX0NoPTMiLAogICAgICAgICAgICAiQzBfTnVtYmVyX29mX1ZveGVscyIsIAogICAgICAgICAgICAiQzBfTnVtYmVyX29mX1RyaWFuZ2xlcyIsCiAgICAgICAgICAgICJDMF9TcGhlcmljaXR5IiwgCiAgICAgICAgICAgICJDMF9Wb2x1bWUuY3N2IiwgCiAgICAgICAgICAgICJDMF9Qb3NpdGlvbi5jc3YiICkKYGBgCiMjYWN0dWFsIHJlYWRpbmcgYW5kIG1ha2luZyB0aGVtIGludG8gZGYgCmBgYHtyfQojIyMjTUcxMzEKI0dldHRpbmcgdGhlIGxpc3Qgb2YgYWxsIHRoZSBzYW1wbGVzIGluIHRoZSBleHBlcmltZW50IApnZnBfaW1hcmlzIDwtIGRpcigifi9JbWFyaXMtZGF0YS8yMDIyL3B1cDFfcmZwLzctMjAtMjItcHVwMS9zdGFibGUvaW1hcmlzL2dmcCIsIGZ1bGwubmFtZXMgPSBUUlVFKQoKI2dldHRpbmcgdGhlIGluZm9ybWF0aW9uIGZvciBpbWFnZUogaW1hZ2UgaW5mbyBmaWxlcwojZ2V0dGluZyBhbGwgdGhlIGltYWdlIGluZm8gdHh0IGZvciBhbGwgdGhlIGltYWdlcyBpbiB0aGUgZXhwZXJpbWVudC4gCmxpc3QuaW1hZ2UuaW5mbyA8LSBsaXN0LmZpbGVzKCJ+L0ltYXJpcy1kYXRhLzIwMjIvcHVwMV9yZnAvNy0yMC0yMi1wdXAxL3N0YWJsZS9pbWFnZV9pbmZvX2ltYWdlSiIgLCBmdWxsLm5hbWVzID0gVFJVRSkKCiNFeHRyYWN0aW5nIGluZm9ybWF0aW9uIGZyb20gdGhlIGltYWdlSiBjc3YgaW50byBhIGRmIHdpdGggYWN0dWFsIHRpbWUgZGlmZmVyZW5jZXMgYmV0d2VlbiBlYWNoIGltYWdlcyAKcmVhbC50aW1lLmludGVydmFsLmRmIDwtIGdldC5pbWFnZS5pbmZvLk9ubHlHRlAobGlzdC5pbWFnZS5pbmZvID0gbGlzdC5pbWFnZS5pbmZvKSAgICAgIAoKI0V4dHJhY3RpbmcgaW5mb3JtYXRpb24gZnJvbSB0aGUgaW1hcmlzIGNzdiBpbnRvIGEgZGYgd2l0aCBpbmZvcm1hdGlvbiBvbiBhcmVhLCB0aW1lLCBnZnAgaW50ZW5zaXR5LCBtY2hlcnJ5IGludGVuc2l0eSwgKG1lYW4sIG1lZGlhbiBhbmQgc3VtKSwgdm9sdW1lLCB0cmFja0lEIGFuZCBJRHMKbGlzdC5vZi5maWxlcy5nZnAgPC0gZ2V0LmltYXJpcy5pbmZvLm9ubHlHRlAoIGRpci5uYW1lcyA9IGdmcF9pbWFyaXMsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZXNfdG9fcmVhZCA9IEZpbGVzVG9SZWFkICwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlYWwudGltZS5pbnRlcnZhbC5kZiA9IHJlYWwudGltZS5pbnRlcnZhbC5kZikKCmxpc3Qub2YuZmlsZXMuZ2ZwJGAyMG1pbmAgJT4lIAogIHNwbGl0KC4kZmllbGQpCgoKYGBgCgoKCiNBc3NpZ25pbmcgdGhlIHNhbXBsZSBieSB0byBlYWNoIGZpZWxkLiBUaGVyZSBhcmUgdHdvIGZpZWxkcyBvZiBhdXRvZmx1b3Jlc2NlY25lIGluIHRoaXMgZXhwZXJpbWVudC4gVGhlIG5lZy5zaW5nYWwgc3RhbmRzIGZvciB0aGUgYXV0b2ZsdW9yZXNjZW5jZSBzYW1wbGUuIApgYGB7cn0KbGlzdC5vZi5maWxlcy5nZnBbWyIyMG1pbiJdXSA8LSBsaXN0Lm9mLmZpbGVzLmdmcFtbIjIwbWluIl1dICU+JSAKICBtdXRhdGUoc2FtcGxlID0gaWZlbHNlKGV4cC5maWVsZCAlaW4lIGMoIjIwbWluX3MxIiwgIjIwbWluX3MyIiksICJuZWcuc2lnbmFsIiwgInBvcy5zaWduYWwiKSkKCmBgYAoKCgojZ2V0dGluZyB0aGUgaW1hcmlzIGluZm8gb2YgREFQSSBhbmQgcHVwMS1yZnAgCiMjZmlsZXMgdG8gcmVhZCAodGhlc2Ugd2lsbCBoYXZlIHJmcCBhbmQgZGFwaSkKIyNVc2UgdGhlIGNlbGxzX3N1cmZhY2UgZGF0YSBmcm9tIEltYXJpcwojZmlsZXMgdG8gcmVhZAoKI3JlYWRpbmcgdGhlIGNlbGwgc3VyZmFjZSBpbWFyaXMgZmlsZXMgCmBgYHtyfQojIGRhcGlfcHVwMV9pbWFyaXNfY2VsbHMgPC0gZGlyKCJ+L0ltYXJpcy1kYXRhLzIwMjIvcHJvdGVhc29tZV9pbmhpYml0aW9uLzItMjMtMjItUEkvMXVNL2ltYXJpcy9zdXJmYWNlL2NlbGxzIiwgZnVsbC5uYW1lcyA9IFRSVUUpIAojIAojIGxpc3Qub2YuZmlsZXMuZGFwaS5wdXAxIDwtIGdldC5pbWFyaXMuaW5mby5kYXBpX3B1cDEoZGlyLm5hbWVzID0gZGFwaV9wdXAxX2ltYXJpc19jZWxscywgCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlc190b19yZWFkID0gRmlsZXNUb1JlYWREQVBJUkZQKQojIAojIHVuaXF1ZShsaXN0Lm9mLmZpbGVzLmRhcGkucHVwMSR0aW1lcG9pbnQpCmBgYAoKCiNnZXR0aW5nIHRoZSBwdXAxLXJmcCBwdW5jdGEgaW5mbwojI3VzZSB0aGUgcHVwMV9zdXJmYWNlIGluZm8gZnJvbSBJbWFyaXMKYGBge3J9CkZpbGVzVG9SZWFkREFQSVJGUCA8LSBjKCJDMF9BcmVhIiwgCiAgICAgICAgICAgICJDMF9Cb3VuZGluZ0JveE9PX0xlbmd0aF9CIiwKICAgICAgICAgICAgIkMwX0JvdW5kaW5nQm94T09fTGVuZ3RoX0MiLAogICAgICAgICAgICAiQzBfRWxsaXBzb2lkX0F4aXNfTGVuZ3RoX0IiLAogICAgICAgICAgICAiQzBfRWxsaXBzb2lkX0F4aXNfTGVuZ3RoX0MiLAogICAgICAgICAgICAiQzBfSW50ZW5zaXR5X0NlbnRlcl9DaD00IiwKICAgICAgICAgICAgIkMwX0ludGVuc2l0eV9NZWFuX0NoPTQiLCAKICAgICAgICAgICAgIkMwX0ludGVuc2l0eV9NZWRpYW5fQ2g9NCIsCiAgICAgICAgICAgICJDMF9JbnRlbnNpdHlfU3VtX0NoPTQiLAogICAgICAgICAgICAiQzBfSW50ZW5zaXR5X0NlbnRlcl9DaD01IiwKICAgICAgICAgICAgIkMwX0ludGVuc2l0eV9NZWFuX0NoPTUiLCAKICAgICAgICAgICAgIkMwX0ludGVuc2l0eV9NZWRpYW5fQ2g9NSIsCiAgICAgICAgICAgICJDMF9JbnRlbnNpdHlfU3VtX0NoPTUiLAogICAgICAgICAgICAiQzBfTnVtYmVyX29mX1ZveGVscyIsIAogICAgICAgICAgICAiQzBfTnVtYmVyX29mX1RyaWFuZ2xlcyIsCiAgICAgICAgICAgICJDMF9TcGhlcmljaXR5IiwgCiAgICAgICAgICAgICJDMF9Wb2x1bWUuY3N2IiwgCiAgICAgICAgICAgICJDMF9Qb3NpdGlvbl9YLmNzdiIsCiAgICAgICAgICAgICJDMF9Qb3NpdGlvbl9ZLmNzdiIsCiAgICAgICAgICAgICJDMF9JbnRlbnNpdHlfTWF4X0NoPTYiLAogICAgICAgICAgICAiQzBfSW50ZW5zaXR5X0NlbnRlcl9DaD02IikKYGBgCgojZmlyc3QgZ2V0IHRoZSBpbmZvIG9mIHRoZSBjZWxsIHN1cmZhY2UgdGhlbiBtYXRjaCBlYWNoIGNlbGwgc3VyZmFjZSB3aXRoIHRoZSBwdXAxIHB1bmN0YS4gCmRvIG5vdCBpbmNsdWRlIHRoZSBNUkcgY2VsbHMgYXMgdGhleSBoYXZlIG5vIHB1cDEtcmZwIHB1bmN0YSBtYXNrCmBgYHtyfQpkYXBpX3B1cDFfaW1hcmlzX2NlbGxzIDwtIGRpcigifi9JbWFyaXMtZGF0YS8yMDIyL3B1cDFfcmZwLzctMjAtMjItcHVwMS9zdGFibGUvaW1hcmlzL3N1cmZhY2UvY2VsbHMiLCBmdWxsLm5hbWVzID0gVFJVRSkgCgpsaXN0Lm9mLmZpbGVzLmRhcGkucHVwMSA8LSBnZXQuaW1hcmlzLmluZm8uZGFwaV9wdXAxLnN1cmZhY2UoZGlyLm5hbWVzID0gZGFwaV9wdXAxX2ltYXJpc19jZWxscywgZmlsZXNfdG9fcmVhZCA9IEZpbGVzVG9SZWFkREFQSVJGUCkgI3VwZGF0ZWQgdGhpcyBmdW5jdGlvbiB0byBub3QgaW5jbHVkZSB0cmFja0lEcwoKbGlzdC5vZi5maWxlcy5kYXBpLnB1cDEgPC0gbGlzdC5vZi5maWxlcy5kYXBpLnB1cDEgJT4lCiAgICBtdXRhdGUodGltZXBvaW50ID0gaWZlbHNlKHRpbWVwb2ludCA9PSAyLDMxLHRpbWVwb2ludCkpCmxpc3Qub2YuZmlsZXMuZGFwaS5wdXAxICU+JSBzcGxpdCguJHRpbWVwb2ludCkKYGBgCgoKI0dldHRpbmcgdGhlIHB1cDEgcHVuY3RhIHN1cmZhY2UgaW5mbyAKYGBge3J9CnB1cDFfc3VyZmFjZV9pbWFyaXMgPC0gZGlyKCJ+L0ltYXJpcy1kYXRhLzIwMjIvcHVwMV9yZnAvNy0yMC0yMi1wdXAxL3N0YWJsZS9pbWFyaXMvc3VyZmFjZS9wdXAxIiwgZnVsbC5uYW1lcyA9IFRSVUUpIAoKcHVwMV9wdW5jdGEgPC0gZ2V0LmltYXJpcy5pbmZvLmRhcGlfcHVwMS5zdXJmYWNlKGRpci5uYW1lcyA9IHB1cDFfc3VyZmFjZV9pbWFyaXNbMzo4XSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlc190b19yZWFkID0gRmlsZXNUb1JlYWREQVBJUkZQKSAKcHVwMV9wdW5jdGEgPC0gcHVwMV9wdW5jdGEgJT4lIAogIG11dGF0ZSh0aW1lcG9pbnQgPSBpZmVsc2UodGltZXBvaW50ID09IDIsMzEsdGltZXBvaW50KSkKCnB1cDFfcHVuY3RhICU+JSBzcGxpdCguJHRpbWVwb2ludCkKYGBgCiAKCgojY29tYmluZSB0aGUgY2VsbCBzdXJmYWNlIGluZm8gd2l0aCB0aGUgcHVwMSBwdW5jdGEgaW5mby4gCmBgYHtyfQojdGhpcyBzaG91bGQgaGF2ZSAxMTE1OSBuby4gb2YgY2VsbHMgCnB1cDEuZGFwaS5jZWxsLnB1bmN0YSA8LSBsaXN0Lm9mLmZpbGVzLmRhcGkucHVwMSAlPiUgI2RmIHdpdGggZW50aXJlIGNlbGwgc2VnbWVudGVkIAogIHNlbGVjdCgKICAgIGFyZWEsCiAgICBwb3MueCwKICAgIHBvcy55LAogICAgdGltZXBvaW50LAogICAgYWxsLm1hc2suaW50Lm1heCwKICAgIGFsbC5tYXNrLmludC5jZW50ZXIsCiAgICByZnAuaW50Lm1lYW4sCiAgICByZnAuaW50Lm1lZGlhbiwKICAgIHJmcC5pbnQuc3VtLAogICAgZGFwaS5pbnQubWVhbiwKICAgIGRhcGkuaW50Lm1lZGlhbiwKICAgIGRhcGkuaW50LnN1bSwKICAgIGV4cGVyaW1lbnQsCiAgICBmaWVsZAogICkgJT4lIAogIGxlZnRfam9pbigKICAgIC4sCiAgICBwdXAxX3B1bmN0YSAlPiUgICAgICAgICNkZiB3aXRoIHRoZSBwdXAxIHB1bmN0YSBzZWdtZW50ZWQgCiAgICAgIHNlbGVjdCgKICAgICAgICByZnAuaW50LmNlbnRlciwKICAgICAgICByZnAuaW50Lm1lYW4sCiAgICAgICAgcmZwLmludC5tZWRpYW4sCiAgICAgICAgcmZwLmludC5zdW0sCiAgICAgICAgZGFwaS5pbnQubWVhbiwKICAgICAgICBkYXBpLmludC5zdW0sCiAgICAgICAgZGFwaS5pbnQubWVkaWFuLAogICAgICAgIGFsbC5tYXNrLmludC5tYXgsCiAgICAgICAgYWxsLm1hc2suaW50LmNlbnRlciwKICAgICAgICBhcmVhLAogICAgICAgIHRpbWVwb2ludCwKICAgICAgICBleHBlcmltZW50LAogICAgICAgIGZpZWxkLAogICAgICAgIG5vLm9mLnZveGVscwogICAgICApICU+JSByZW5hbWUoImFyZWEucHVuY3RhIiA9ICJhcmVhIiwKICAgICAgICAgICAgICAgICAgICJyZnAuY2VudGVyLnB1bmN0YSIgPSAicmZwLmludC5jZW50ZXIiLAogICAgICAgICAgICAgICAgICAgInJmcC5tZWFuLnB1bmN0YSIgPSAicmZwLmludC5tZWFuIiwKICAgICAgICAgICAgICAgICAgICJyZnAuc3VtLnB1bmN0YSIgPSAicmZwLmludC5zdW0iLAogICAgICAgICAgICAgICAgICAgInJmcC5tZWRpYW4ucHVuY3RhIiA9ICJyZnAuaW50Lm1lZGlhbiIsCiAgICAgICAgICAgICAgICAgICAiZGFwaS5tZWFuLnB1bmN0YSIgPSAiZGFwaS5pbnQubWVhbiIsCiAgICAgICAgICAgICAgICAgICAiZGFwaS5zdW0ucHVuY3RhIiA9ICJkYXBpLmludC5zdW0iLAogICAgICAgICAgICAgICAgICAgImRhcGkubWVkaWFuLnB1bmN0YSIgPSAiZGFwaS5pbnQubWVkaWFuIiwKICAgICAgICAgICAgICAgICAgICJuby5vZi52b3hlbHMucHVuY3RhIiA9ICJuby5vZi52b3hlbHMiKSwKICAgICBieSA9IGMoImFsbC5tYXNrLmludC5tYXgiICwgCiAgICAgICAgICAgICJleHBlcmltZW50IiAsIAogICAgICAgICAgICAiZmllbGQiICwgCiAgICAgICAgICAgICJ0aW1lcG9pbnQiICwgCiAgICAgICAgICAgICJhbGwubWFzay5pbnQuY2VudGVyIikKICApCgoKICAKI3RoaXMgaGFzIDY1MTQgY2VsbHMuIHNvbWUgY2VsbHMgaGF2ZSBtdWx0aXBsZSBwdW5jdGEuIG1heWJlIGp1c3QgZHJvcCB0aGUgY2VsbHMuIApgYGAKCgojY29tYmluZSB0aGUgY2VsbCBzdXJmYWNlICsgcHVwMSBwdW5jdGEgaW5mbyBvZiB0aGUgcHVwMSBleHByZXNzaW5nIGNlbGxzIHdpdGggYWxsIHRoZSBjZWxsIHN1cmZhY2UgaW5mb3JtYXRpb24uIFRoZXJlIHdpbGwgYmUgTkFzIGluIHRoZSBjb2x1bW5zIHdpdGggcHVuY3RhIGluIHRoZWlyIG5hbWVzIGZvciB0aGUgbmVnIGNlbGxzIApgYGB7cn0KIyBwdXAxLmRhcGkuYWxsIDwtIGxpc3Qub2YuZmlsZXMuZGFwaS5wdXAxICU+JSAKIyAgIGxlZnRfam9pbiguLHB1cDEuZGFwaS5jZWxsLnB1bmN0YSAlPiUgCiMgICAgICAgICAgICAgICBzZWxlY3QoLixhcmVhLCAKIyAgICAgICAgICAgICAgICAgICAgICBwb3MueCwgCiMgICAgICAgICAgICAgICAgICAgICAgcG9zLnksCiMgICAgICAgICAgICAgICAgICAgICAgdGltZXBvaW50LAojICAgICAgICAgICAgICAgICAgICAgIGV4cGVyaW1lbnQsIAojICAgICAgICAgICAgICAgICAgICAgIGZpZWxkLCAKIyAgICAgICAgICAgICAgICAgICAgICByZnAuY2VudGVyLnB1bmN0YSwgcmZwLm1lYW4ucHVuY3RhLCByZnAubWVkaWFuLnB1bmN0YSwgcmZwLnN1bS5wdW5jdGEsCiMgICAgICAgICAgICAgICAgICAgICAgZGFwaS5tZWFuLnB1bmN0YSxkYXBpLnN1bS5wdW5jdGEsIGRhcGkubWVkaWFuLnB1bmN0YSwKIyAgICAgICAgICAgICAgICAgICAgICBhcmVhLnB1bmN0YSwgbm8ub2Yudm94ZWxzLnB1bmN0YSksIAojICAgICAgICAgICAgIGJ5ID0gYygiYXJlYSIsInBvcy54IiwicG9zLnkiLCJ0aW1lcG9pbnQiLCAiZXhwZXJpbWVudCIsICJmaWVsZCIpKQojIAojIHB1cDEuZGFwaS5hbGwKCiNkb250IG5lZWQgdG8gZG8gdGhpcy4gCmBgYAoKCkNvbWJpbmluZyB0aGUgR0ZQIGludGVuc2l0aWVzIHdpdGggdGhlIHJmcCBwdW5jdGEgaW5mbyBhdCB0ID0gMSAKYGBge3J9CmNlbGxfYXRyaWJ1dGVzIDwtIGxpc3Qub2YuZmlsZXMuZ2ZwJGAyMG1pbmAgJT4lIAogIGZpbHRlcih0aW1lcG9pbnQgJWluJSBjKDEsMzEpKSAlPiUgCiAgbGVmdF9qb2luKC4scHVwMS5kYXBpLmNlbGwucHVuY3RhICU+JSBzZWxlY3QoLWFsbC5tYXNrLmludC5tYXgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLWFsbC5tYXNrLmludC5jZW50ZXIpICwKICAgICAgICAgICAgYnkgPSBjKCJhcmVhIiwKICAgICAgICAgICAgICAgICAgICJ0aW1lcG9pbnQiLAogICAgICAgICAgICAgICAgICAgInBvcy54IiwKICAgICAgICAgICAgICAgICAgICJwb3MueSIsCiAgICAgICAgICAgICAgICAgICAiZXhwZXJpbWVudCIsCiAgICAgICAgICAgICAgICAgICAiZmllbGQiKSkKCmNlbGxfYXRyaWJ1dGVzICU+JSAKICAjIGZpbHRlcih1bmlxdWUudHJhY2tJRCA9PSAiMTAwMDAwMTc3NF8yMG1pbl9zMyIpCiAgICBkcGx5cjo6Z3JvdXBfYnkoZmllbGQsIHVuaXF1ZS50cmFja0lELCB0aW1lcG9pbnQpICU+JQogICAgZHBseXI6OnN1bW1hcmlzZShuID0gZHBseXI6Om4oKSwgLmdyb3VwcyA9ICJkcm9wIikgJT4lCiAgICBkcGx5cjo6ZmlsdGVyKG4gPiAxTCkKIzY0NDAgY2VsbHMuIFRoZXJlIGFyZSA2IGNlbGxzIHdpdGggbXVsdGlwbGUgcHVwMSBwdW5jdGEuIG1heWJlIGRyb3AgdGhlc2UgY2VsbHMganVzdCBmb3Igc2ltcGxpY2l0eSBwdXJwb3Nlcy4gCmBgYAoKI0JhY2tncm91bmQgc3VidHJhY3Rpb24gCmBgYHtyfQojYmFja2dyb3VuZCBpbmZvIGZpbGVzIGZvciBnZnAgYW5kIG1jaGVycnkgYW5kIERBUEk6IHRoZSBiYWNrZ3JvdW5kIGZvbGRlciBoYXMgdHdvIGRpcmVjdG9yaWVzOiBnZnAgYmcgYW5kIG1jaGVycnkrZGFwaSBiZwpiZyA8LSBkaXIocGF0aCA9ICJ+L0ltYXJpcy1kYXRhLzIwMjIvcHVwMV9yZnAvNy0yMC0yMi1wdXAxL3N0YWJsZS9iYWNrZ3JvdW5kIiAsIGZ1bGwubmFtZXMgPSBUUlVFKQoKI0dldCB0aGUgaW5mb3JtYXRpb24gZm9yIHRoZSBiYWNrZ3JvdW5kIGludGVuc2l0eSBmb3IgZXZlcnkgaW1hZ2UgZm9yIAojcmZwIGFuZCBEQVBJCnJmcC5kYXBpLmJnLm1lYW5zIDwtIGJnLmludGVuc2l0eS5yZnAuZGFwaShiZy5maWxlcyA9IGxpc3QuZmlsZXMoYmdbMV0gLCBmdWxsLm5hbWVzID0gVFJVRSkpCnJmcC5kYXBpLmJnLm1lYW5zCgojZm9yIEdGUApnZnAuYmcubWVhbiA8LSBiZy5pbnRlbnNpdHkuZ2ZwKGJnLmZpbGVzID0gbGlzdC5maWxlcyhiZ1syXSAsIGZ1bGwubmFtZXMgPSBUUlVFKSkKCmdmcC5iZy5tZWFuJGAyMG1pbmAgJT4lIGFycmFuZ2UoZmllbGQsdGltZXBvaW50KQpgYGAKCgoKI2dmcCBiYWNrZ3JvdW5kIGZvciBzNCwgczUgYW5kIHM2IHNhbXBsZXM6CmBgYHtyfQpzMS4zLjQuNS42LjcuOC5nZnAuYmdfZmlsZXMgPC0gbGlzdC5maWxlcygifi9JbWFyaXMtZGF0YS8yMDIyL3B1cDFfcmZwLzctMjAtMjItcHVwMS9zdGFibGUvYmFja2dyb3VuZC9iZ19nZnBfczMiLCBmdWxsLm5hbWVzID0gVCkKCmdmcC5iZy5tZWFuLnMxLjMuNC41LjYuNy44IDwtIGxhcHBseShzMS4zLjQuNS42LjcuOC5nZnAuYmdfZmlsZXMsIGZ1bmN0aW9uKGEpewogIHJlYWQuY3N2KGEpICU+JSAKICBtdXRhdGUoZmllbGQgPSBzdHJfc3BsaXQoTGFiZWwsICJfIiwgc2ltcGxpZnkgPSBUKVssbmNvbChzdHJfc3BsaXQoTGFiZWwsICJfIiwgc2ltcGxpZnkgPSBUKSktMl0sCiAgICAgICAgIHRpbWVwb2ludCA9IGFzLm51bWVyaWMoc3RyX3JlbW92ZShzdHJfc3BsaXQoTGFiZWwsICJfIiwgc2ltcGxpZnkgPSBUKVssbmNvbChzdHJfc3BsaXQoTGFiZWwsICJfIiwgc2ltcGxpZnkgPSBUKSktMV0sICJ0IikpKSAlPiUgCiAgc2VsZWN0KGZpZWxkLAogICAgICAgICB0aW1lcG9pbnQsCiAgICAgICAgIE1lYW4sCiAgICAgICAgIE1pbikgJT4lIAogIGdyb3VwX2J5KHRpbWVwb2ludCwgZmllbGQpICU+JSAKICBzdW1tYXJpc2UoYXZnLmdmcC5iZyA9IG1lYW4oTWVhbikpCn0pICU+JSBiaW5kX3Jvd3MoKQoKZ2ZwLmJnLm1lYW4kYDIwbWluYCA8LSBnZnAuYmcubWVhbiRgMjBtaW5gICU+JSAKICBsZWZ0X2pvaW4oLixnZnAuYmcubWVhbi5zMS4zLjQuNS42LjcuOCwgYnkgPSBjKCJmaWVsZCIsICJ0aW1lcG9pbnQiKSkgJT4lIAogIG11dGF0ZShhdmcuZ2ZwLmJnID0gaWZlbHNlKGlzLm5hKGF2Zy5nZnAuYmcpLCBNZWFuX2dmcCwgYXZnLmdmcC5iZykpIAoKZ2ZwLmJnLm1lYW4kYDIwbWluYCAlPiUgCiAgZ3JvdXBfYnkoZmllbGQpICU+JSAKICBhcnJhbmdlKGZpZWxkLCB0aW1lcG9pbnQpCmBgYAoKYGBge3J9CnMxLjMuNC41LjYuNy44LnJmcC5kYXBpIDwtIGxpc3QuZmlsZXMoIn4vSW1hcmlzLWRhdGEvMjAyMi9wdXAxX3JmcC83LTIwLTIyLXB1cDEvc3RhYmxlL2JhY2tncm91bmQvYmdfbWNoZXJyeV9kYXBpX3MzIiwgZnVsbC5uYW1lcyA9IFQpCgpyZnAuYmcubWVhbi5zNS5zNy5zOCA8LSBsYXBwbHkoczEuMy40LjUuNi43LjgucmZwLmRhcGksIGZ1bmN0aW9uKGEpewogIHJlYWQuY3N2KGEpICU+JQogIG11dGF0ZShmaWVsZCA9IHN0cl9zcGxpdChMYWJlbCwgIl8iLCBzaW1wbGlmeSA9IFQpWyxuY29sKHN0cl9zcGxpdChMYWJlbCwgIl8iLCBzaW1wbGlmeSA9IFQpKS0yXSwKICAgICAgICAgdGltZXBvaW50ID0gYXMubnVtZXJpYyhzdHJfcmVtb3ZlKHN0cl9zcGxpdChMYWJlbCwgIl8iLCBzaW1wbGlmeSA9IFQpWyxuY29sKHN0cl9zcGxpdChMYWJlbCwgIl8iLCBzaW1wbGlmeSA9IFQpKS0xXSwgInQiKSksCiAgICAgICAgICBjaGFubmVsID0gc3RyX3NwbGl0KExhYmVsLCAiXyIsIHNpbXBsaWZ5ID0gVClbLG5jb2woc3RyX3NwbGl0KExhYmVsLCAiXyIsIHNpbXBsaWZ5ID0gVCkpXSkgJT4lCiAgbXV0YXRlKGNoYW5uZWwgPSBpZmVsc2UoY2hhbm5lbCA9PSAiQzQiLCAiRGFwaSIsICJtY2hlcnJ5IikpICU+JQogIHNlbGVjdChmaWVsZCwKICAgICAgICAgdGltZXBvaW50LAogICAgICAgICBjaGFubmVsLAogICAgICAgICBNZWFuLAogICAgICAgICBNaW4pICU+JQogIGdyb3VwX2J5KHRpbWVwb2ludCwgZmllbGQsIGNoYW5uZWwpICU+JQogIHN1bW1hcmlzZShhdmcuZ2ZwLmJnID0gbWVhbihNZWFuKSkgJT4lCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IGNoYW5uZWwsCiAgICAgICAgICAgICAgdmFsdWVzX2Zyb20gPSBhdmcuZ2ZwLmJnKQp9KSAlPiUgYmluZF9yb3dzKCkKCnJmcC5kYXBpLmJnLm1lYW5zJGAyMG1pbmAgPC0gcmZwLmRhcGkuYmcubWVhbnMkYDIwbWluYCAlPiUKICBsZWZ0X2pvaW4oLixyZnAuYmcubWVhbi5zNS5zNy5zOCwgYnkgPSBjKCJmaWVsZCIsICJ0aW1lcG9pbnQiKSkgJT4lCiAgbXV0YXRlKERhcGkgPSBpZmVsc2UoaXMubmEoRGFwaSksIGF2Zy5kYXBpLmJnLCBEYXBpKSwKICAgICAgICAgbWNoZXJyeSA9IGlmZWxzZShpcy5uYShtY2hlcnJ5KSwgYXZnLnJmcC5iZywgbWNoZXJyeSkpICU+JQogIHNlbGVjdCgtYXZnLmRhcGkuYmcsCiAgICAgICAgIC1hdmcucmZwLmJnKSAlPiUKICByZW5hbWUoImF2Zy5kYXBpLmJnIiA9ICJEYXBpIiwKICAgICAgICAgImF2Zy5yZnAuYmciID0gIm1jaGVycnkiKQpgYGAKCiNhY3R1YWxseSBzdWJ0cmFjdCB0aGUgYmFja2dyb3VuZCBpbnRlbnNpdHkgZnJvbSB0aGUgZ2ZwIGFuZCBtY2hlcnJ5IGludGVuc2l0eSBvZiB0aGUgY2VsbHMKYGBge3J9CiNmaXJzdCBmdW4uIHN1Yi5iZy5pbnRlbnNpdHkgc3VidHJhY3RzIHRoZSBiZyBpbnRlbnNpdHkgZnJvbSBlYWNoIGNlbGwuIAoKZ2ZwLmJnLnN1YiA8LSBzdWIuYmcuaW50ZW5zaXR5LmdmcChsaXN0Lm9mLmZpbGVzID0gbGlzdC5vZi5maWxlcy5nZnAsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJnLm1lYW5zID0gZ2ZwLmJnLm1lYW4kYDIwbWluYCAgKQpnZnAuYmcuc3ViCgpyZnAuZGFwaS5iZy5zdWIgPC0gc3ViLmJnLmludGVuc2l0eS5kYXBpLnJmcChsaXN0Lm9mLmZpbGVzID0gY2VsbF9hdHJpYnV0ZXMsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiZy5tZWFucyA9IHJmcC5kYXBpLmJnLm1lYW5zJGAyMG1pbmAgKQoKZ2ZwLmJnLnN1YiRgMjBtaW5gICU+JSAKICBmaWx0ZXIoZ2ZwLm1lYW4uYmcuc3ViID4gMCwKICAgICAgICAgKSAlPiUgCiAgZ3JvdXBfYnkoZmllbGQsIHRpbWVwb2ludCkgJT4lIAogIHRhbGx5KCkgCgpyZnAuZGFwaS5iZy5zdWIkYDIwbWluYCAlPiUgc3BsaXQoLiRmaWVsZCkKCmBgYAoKI2NvbWJpbmUgdGhlIGJhY2tncm91bmQgc3VidHJhY3RlZCBnZnAgZGF0YWZyYW1lIHdpdGggdGhlIGJnIHN1YnRyYWN0ZWQgcmZwL2RhcGkgdG90YWwgYW5kIHB1bmN0YSBkZnMKYGBge3J9CmdmcC5yZnAuZGFwaS5iZy5zdWIgPC0gZ2ZwLmJnLnN1YiRgMjBtaW5gICU+JSAKICBmaWx0ZXIodGltZXBvaW50ICVpbiUgYygxLDMxKSkgJT4lIAogIHNlbGVjdCh1bmlxdWUudHJhY2tJRCwKICAgICAgICAgZ2ZwLm1lYW4uYmcuc3ViLAogICAgICAgICBnZnAuc3VtLmJnLnN1YiwKICAgICAgICAgYXZnLmdmcC5iZywKICAgICAgICAgYXJlYSwKICAgICAgICAgcG9zLngsCiAgICAgICAgIHBvcy55KSAlPiUgCiAgbGVmdF9qb2luKC4scmZwLmRhcGkuYmcuc3ViJGAyMG1pbmAsIGJ5ID0gYygidW5pcXVlLnRyYWNrSUQiLCAiYXJlYSIsInBvcy54IiwicG9zLnkiKSkgJT4lIHNwbGl0KC4kZXhwZXJpbWVudCkKCgpgYGAKCgojZmlsdGVyaW5nIGNlbGxzIHdoaWNoIGhhdmUgbmVnYXRpdmUgYmFja2dyb3VuZCBzdWJ0cmFjdGVkIGludGVuc2l0aWVzIApgYGB7cn0KI1VuaXFlIHRyYWNrSURzIG9mIGNlbGxzIGFib3ZlIHRoZSBiYWNrZ3JvdW5kIGludCBmb3IgZ2ZwLCBkYXBpIGFuZCByZnAgCiN0aGlzIGZ1bmN0aW9uIHJlc3VsdHMgaW4gYSBsaXN0IG9mIHR3byBkZnMuIHRoZSAxc3QgZGYgPSB1bmlxdWV0cmFja0lEcyB3aXRoIHRoZSBleHBlcmltZW50IHRoZXkncmUgZnJvbS4KbGlzdE9mVW5pcXRyYWNrSURfZ2ZwZmlsdGVyZWRkZiA8LSB0cmFja0lELmFidi56ZXJvLmdmcC5yZnAuZGFwaSgKICBiZ19zdWJ0cmFjdGVkX2RmdHAxID0gZ2ZwLnJmcC5kYXBpLmJnLnN1YiwKICBsaXN0X2dmcF9hbGxfdHBzID0gZ2ZwLmJnLnN1YikKYGBgCgpgYGB7cn0KI3RoZSBkZiB3aXRoIGdmcCBpbnRlbnNpdGllcyBmb3IgYWxsIHRpbWVwb2ludHMgd2hpY2ggaXMgZmlsdGVyZWQgZm9yIGNlbGxzIGdmcC5tZWFuLmJnLnN1YiA+IDAgCmxpc3Qub2YuZmlsZXMuYmcuc3ViLmFib3ZlLjAuZ2ZwIDwtIGxpc3RPZlVuaXF0cmFja0lEX2dmcGZpbHRlcmVkZGZbWzJdXSAlPiUgCiAgc3BsaXQoLiRleHBlcmltZW50KQpgYGAKCgoKI3JlbW92aW5nIGNlbGxzIHdpdGggbmVnYXRpdmUgYmFja2dyb3VuZCBzdWJ0cmFjdGVkIGludGVuc2l0aWVzIGZyb20gdGhlIGRhdGFmcmFtZSB3aXRoIHRoZSBjZWxsIGluZm8gZnJvbSB0aW1lcG9pbnQgMSBhbmQgdGhlIGxhc3QgdGltZXBvaW50CmBgYHtyfQpnZnBfcmZwX2RhcGlfYmdzdWJBYnZaZXJvX3RwMSA8LSBsaXN0T2ZVbmlxdHJhY2tJRF9nZnBmaWx0ZXJlZGRmW1sxXV0gJT4lIAogIGxlZnRfam9pbiguLGJpbmRfcm93cyhnZnAucmZwLmRhcGkuYmcuc3ViKSAsIGJ5ID0gYygidW5pcXVlLnRyYWNrSUQiLCAiZXhwZXJpbWVudCIpKQoKZ2ZwX3JmcF9kYXBpX2Jnc3ViQWJ2WmVyb190cDEgJT4lIAogIGdyb3VwX2J5KHRpbWVwb2ludCwgZXhwLmZpZWxkKSAlPiUgCiAgdGFsbHkoKQoKbGlzdC5vZi5maWxlcy5iZy5zdWIuYWJvdmUuMC5nZnAkYDIwbWluYCU+JSAKICBncm91cF9ieSh0aW1lcG9pbnQsIGV4cC5maWVsZCkgJT4lIHRhbGx5KCkKYGBgCiNzMywgczQsIHM1LCBzNiwgczcgYW5kIHM4IG5lZWQgdG8gZml4IHRoZSBiYWNrZ3JvdW5kIHN1YnRyYWN0aW9uCgojZGVuc2l0eSBwbG90IG9mIHRoZSBEQVBJIHN0YWluaW5nLiBIaWdoZXIgREFQSSBzdGFpbmluZyA9PSBkZWFkIGNlbGxzIApgYGB7ciBmaWcuaGVpZ2h0PSA4ICwgZmlnLndpZHRoPSAxM30KI2F0IHRoZSBmaXJzdCB0aW1lcG9pbnQKZ2ZwX3JmcF9kYXBpX2Jnc3ViQWJ2WmVyb190cDEgICU+JSAKICBnZ3Bsb3QoLixhZXMoeCA9IGRhcGkubWVhbi5iZy5zdWIsIGNvbG9yID0gYXMuZmFjdG9yKHRpbWVwb2ludCkpKSsKICBnZW9tX2RlbnNpdHkoYWVzKHk9Li5zY2FsZWQuLikpKwogIGZhY2V0X3dyYXAofmZpZWxkLCBzY2FsZXMgPSAiZnJlZV94IikrCiAgc2NhbGVfeF9sb2cxMCgpKwogIHRoZW1lX3B1YnIoeC50ZXh0LmFuZ2xlID0gNDUpCgoKI2NvcnJlbGF0aW9uIG9mIHRoZSBkYXBpIHN0YWluaW5nIGF0IHRpbWVwaW50IDEgYW5kIHRoZSBsYXN0IHRpbWVwb2ludAojIGdmcF9yZnBfZGFwaV9iZ3N1YkFidlplcm9fdHAxICAlPiUKIyAgIHNlbGVjdChkYXBpLm1lYW4uYmcuc3ViLCB0aW1lcG9pbnQsIGZpZWxkLCB1bmlxdWUudHJhY2tJRCkgJT4lCiMgICBmaWx0ZXIoISh1bmlxdWUudHJhY2tJRCA9PSAiMTAwMDAwMDI1OV8yMG1pbl9zOCIpKSAlPiUgCiMgICBwaXZvdF93aWRlcih2YWx1ZXNfZnJvbSA9IGRhcGkubWVhbi5iZy5zdWIsIG5hbWVzX2Zyb20gPSB0aW1lcG9pbnQpICU+JSAKIyAgIGdncGxvdCguLGFlcyh4ID0gYDFgLCB5ID0gYDMxYCkpKwojICAgZ2VvbV9wb2ludCgpKwojICAgZmFjZXRfd3JhcCh+ZmllbGQsIHNjYWxlcyA9ICJmcmVlX3giKSsKIyAgIHRoZW1lX3B1YnIoeC50ZXh0LmFuZ2xlID0gNDUpCgojdGhlIGFib3ZlIGNvZGUgZGlkIG5vdCB3b3JrIGJlY2F1c2UgdGhlcmUgYXJlIGR1cGxpY2F0ZSB2YWx1ZXMgZm9yIGEgZ2l2ZW4gY2VsbCBJRC4gCgojdG8gZmluZCB0aGUgZHVwbGljYXRlcwpnZnBfcmZwX2RhcGlfYmdzdWJBYnZaZXJvX3RwMSAgJT4lIAogIHNlbGVjdChkYXBpLm1lYW4uYmcuc3ViLCB0aW1lcG9pbnQsIGZpZWxkLCB1bmlxdWUudHJhY2tJRCkgJT4lCiAgICBkcGx5cjo6Z3JvdXBfYnkoZmllbGQsIHVuaXF1ZS50cmFja0lELCB0aW1lcG9pbnQpICU+JQogICAgZHBseXI6OnN1bW1hcmlzZShuID0gZHBseXI6Om4oKSwgLmdyb3VwcyA9ICJkcm9wIikgJT4lCiAgICBkcGx5cjo6ZmlsdGVyKG4gPiAxTCkKCiNyZW1vdmUgdGhlIGR1cGxpY2F0ZXMgYW5kIGxvb2sgYXQgaG93IGRhcGkgc3RhaW5pbmcgaXMgY2hhbmdpbmcgZnJvbSB0aW1lcG9pbnQgMSB0byB0cCAzMToKI2NvcnJlbGF0aW9uIG9mIHRoZSBkYXBpIHN0YWluaW5nIGF0IHRpbWVwaW50IDEgYW5kIHRoZSBsYXN0IHRpbWVwb2ludApnZnBfcmZwX2RhcGlfYmdzdWJBYnZaZXJvX3RwMSAgJT4lCiAgc2VsZWN0KGRhcGkubWVhbi5iZy5zdWIsIHRpbWVwb2ludCwgZmllbGQsIHVuaXF1ZS50cmFja0lEKSAlPiUKICBmaWx0ZXIoISh1bmlxdWUudHJhY2tJRCA9PSAiMTAwMDAwMjA3MV8yMG1pbl9zOCIpKSAlPiUgCiAgcGl2b3Rfd2lkZXIodmFsdWVzX2Zyb20gPSBkYXBpLm1lYW4uYmcuc3ViLCBuYW1lc19mcm9tID0gdGltZXBvaW50KSAlPiUgCiAgZ2dwbG90KC4sYWVzKHggPSBgMWAsIHkgPSBgMzFgKSkrCiAgZ2VvbV9wb2ludCgpKwogIGZhY2V0X3dyYXAofmZpZWxkLCBzY2FsZXMgPSAiZnJlZV94IikrCiAgdGhlbWVfcHVicih4LnRleHQuYW5nbGUgPSA0NSkKYGBgCgoKI2dldCB0aGUgdGhyZXNob2xkIG9mIGRhcGkgYWJvdmUgd2hpY2ggdGhlIGNlbGxzIHdpbGwgYmUgZGVlbWVkIGRlYWQhIQpgYGB7ciBmaWcuaGVpZ2h0PSA4ICwgZmlnLndpZHRoPSAxM30KI3NwbGl0IHRoZSBkZiBpbnRvIHRoZSBleHBlcmltZW50cyBzbyB0aGF0IHRoZXJlIGlzIGEgZGVhZCBjZWxsIHRocmVzaG9sZCBmb3IgZXZlcnkgZXhwZXJpbWVudCAKZGVhZGNlbGxfdGVtcF9kZiA8LSBnZnBfcmZwX2RhcGlfYmdzdWJBYnZaZXJvX3RwMSAlPiUgCiAgc3BsaXQoLiRleHBlcmltZW50KSAKCgpkZWFkQ2VsbF9ib3VuZHJ5IDwtIGRhcGkudGhyZXNob2xkKGRmX2Zvcl90aHJlc2hvbGQgPSBkZWFkY2VsbF90ZW1wX2RmICwgbG93ZXJfbGltID0gMzAwLCB1cHByX2xpbSA9IDEwMDAgKSAlPiUgCiAgcmVuYW1lKCJleHAuZmllbGQiID0gImV4cGVyaW1lbnQiKQoKCiNhdCB0aGUgZmlyc3QgdGltZXBvaW50CmdmcF9yZnBfZGFwaV9iZ3N1YkFidlplcm9fdHAxICU+JSAKICBmaWx0ZXIodGltZXBvaW50ID09IDEpICU+JSAKICBsZWZ0X2pvaW4oLixkZWFkQ2VsbF9ib3VuZHJ5ICwgYnkgPSAiZXhwLmZpZWxkIikgJT4lIAogIGdncGxvdCguLGFlcyh4ID0gZGFwaS5tZWFuLmJnLnN1YiwgY29sb3IgPSBzYW1wbGUpKSsKICBnZW9tX2RlbnNpdHkoYWVzKHk9Li5zY2FsZWQuLikpKwogIGdlb21fdmxpbmUoZGF0YT0gZGVhZENlbGxfYm91bmRyeSwgYWVzKHhpbnRlcmNlcHQgPSBkYXBpLnRocmVzaG9sZCkpKwogIGZhY2V0X3dyYXAofmV4cC5maWVsZCwgc2NhbGVzID0gImZyZWVfeCIpKwogIHNjYWxlX3hfbG9nMTAoKSsKICBhbm5vdGF0aW9uX2xvZ3RpY2tzKCkrCiAgdGhlbWVfcHVicih4LnRleHQuYW5nbGUgPSA0NSkKCmBgYAoKCiNyZW1vdmluZyBjZWxscyB3aXRoIGRhcGkgaW50ZW5zaXR5IGdyZWF0ZXIgdGhhbiB0aGUgZGFwaSB0aHJlc2hvbGQgc2V0CmBgYHtyfQojZ2V0dGluZyB0aGUgSURzIG9mIHRoZSBjZWxscyByZW1haW5pbmcgYWZ0ZXIgcmVtb3ZpbmcgdGhlIGNlbGxzIHdpdGggaGlnaGVyIHRoYW4gdGhyZXNob2xkIGRhcGkgaW50ZW5zaXR5LiB1c2UgdGhpcyB0byBmaWx0ZXIgY2VsbHMgZnJvbSB0aGUgZGYgd2l0aCBtY2hlcnJ5IGFuZCBnZnAgdGltZWxhcHNlIGluZm9ybWF0aW9uCiN3aWxsIHJlbW92ZSBkZWFkIGNlbGxzIGZyb20gdGhlIGZpcnN0IHRpbWVwb2ludCAKZGFwaS5maWx0ZXJlZC5jZWxsc1RyYWNrSUQgPC0gYmluZF9yb3dzKGRlYWRjZWxsX3RlbXBfZGYpICU+JSAKICBmaWx0ZXIodGltZXBvaW50ICVpbiUgYygxLDMxKSkgJT4lIAogIGxlZnRfam9pbiguLGRlYWRDZWxsX2JvdW5kcnksIGJ5ID0gImV4cC5maWVsZCIpICU+JSAKICBmaWx0ZXIoZGFwaS5tZWFuLmJnLnN1YiA8IGRhcGkudGhyZXNob2xkKSAlPiUgcHVsbCh1bmlxdWUudHJhY2tJRCkKCiNkZiB3aXRoIGZsdW9yZXNjZW50IGludGVuc2l0aWVzIG9mIGdmcCwgcmZwIGFuZCBkYXBpIGZvciBsaXZlIGNlbGxzIGF0IHRwID0xIGFudCB0cCA9IDMxLgpsaXZlQ2VsbHNSRlAuREFQSS5HRlAgPC0gZ2ZwX3JmcF9kYXBpX2Jnc3ViQWJ2WmVyb190cDEgJT4lIAogIGxlZnRfam9pbiguLGRlYWRDZWxsX2JvdW5kcnksIGJ5ID0gImV4cC5maWVsZCIpICU+JSAKICBmaWx0ZXIoZGFwaS5tZWFuLmJnLnN1YiA8IGRhcGkudGhyZXNob2xkKQoKCiNkZiB3aXRoIGRlYWQgY2VsbHMgcmVtb3ZlZCB0aGlzIGRmIGhhcyBnZnAgaW50ZW5zaXRpZXMgZm9yIGFsbCB0aGUgdGltZXBvaW50IHdoaWNoIGFyZSBmaWx0ZXJlZCBmb3IgZGVhZCBjZWxscyAKbmV3LmdmcExpdmVDZWxscyA8LSAgYmluZF9yb3dzKGxpc3Qub2YuZmlsZXMuYmcuc3ViLmFib3ZlLjAuZ2ZwKSAlPiUgCiAgZmlsdGVyKHVuaXF1ZS50cmFja0lEICVpbiUgbGl2ZUNlbGxzUkZQLkRBUEkuR0ZQJHVuaXF1ZS50cmFja0lEKQpgYGAKCgojc2F2aW5nIHRoZSBkYXRhZnJhbWUgd2l0aCB0aGUgYmFja2dyb3VuZCBzdWJ0cmFjdGVkLCBkZWFkIGNlbGxzIGZpbHRlcmVkIGludGVuc2l0aWVzIG9mIGdmcHMgZnJvbSB0aGUgYXV0b2ZsdW9yIGNlbGxzIChNUkcpIGFuZCB0aGUgZ2ZwIHBvc2l0aXZlIGNlbGxzLiAKYGBge3J9Cm5ldy5nZnBMaXZlQ2VsbHMgJT4lIAogIHdyaXRlX2NzdiguLHBhdGggPSAifi9wbG90cy9wdXAxLXJmcC1nZnAtZGVjYXkvNy0yMC0yMi1zdGFibGUtZ2ZwL2RhdGEvcmF3X2dmcF9pbnRfYWxsLmNzdiIpCmBgYAoKCmxvb2tpbmcgYXQgdGhlIGRpc3RyaWJ1dGlvbiBvZiByZnAgYW5kIGdmcCBpbiB0aGUgbGl2ZSBjZWxscyAKYGBge3J9CiNhdXRvZmx1cmVzZW5jZSBvZiBwdXAxLXJmcApsaXZlQ2VsbHNSRlAuREFQSS5HRlAgJT4lIAogIGZpbHRlcih0aW1lcG9pbnQgPT0gMSkgJT4lIAogIGdncGxvdCguLGFlcyh4ID1yZnAubWVhbi5iZy5zdWIgLCBjb2xvciA9IHNhbXBsZSkgKSsKICBnZW9tX2RlbnNpdHkoYWVzKHkgPSAuLnNjYWxlZC4uKSkrCiAgc2NhbGVfeF9sb2cxMCgpKyAKICBmYWNldF93cmFwKH5leHBlcmltZW50KSsKICBhbm5vdGF0aW9uX2xvZ3RpY2tzKCkKCmxpdmVDZWxsc1JGUC5EQVBJLkdGUCAlPiUgCiAgZmlsdGVyKHRpbWVwb2ludCA9PSAxKSAlPiUgCiAgZmlsdGVyKHNhbXBsZSA9PSAicG9zLnNpZ25hbCIpICU+JSAKICBnZ3Bsb3QoLixhZXMoeCA9cmZwLm1lYW4uYmcuc3ViLnB1bmN0YSAsIHkgPSBnZnAubWVhbi5iZy5zdWIpICkrCiAgZ2VvbV9wb2ludCgpKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIpKwogIHNjYWxlX3hfbG9nMTAoKSsgCiAgc2NhbGVfeV9sb2cxMCgpCgoKI2F1dG9mbHVvcmVzY2VuY2UgdnMgZ2ZwIHNpZ25hbCAKbGl2ZUNlbGxzUkZQLkRBUEkuR0ZQICU+JSAKICBmaWx0ZXIodGltZXBvaW50ID09IDEpICU+JSAKICBnZ3Bsb3QoLixhZXMoeCA9IGdmcC5tZWFuLmJnLnN1YiwgY29sb3IgPSBzYW1wbGUpKSsKICBnZW9tX2RlbnNpdHkoYWVzKHkgPSAuLnNjYWxlZC4uKSkrCiAgc2NhbGVfeF9sb2cxMCgpKwogIGZhY2V0X3dyYXAofmZpZWxkLCBzY2FsZXMgPSAiZnJlZV94IikKYGBgCgojcGxvdHRpbmcgbGluZSBwbG90cyByYXcgd2l0aG91dCBhbnkgQUYgZmlsdGVyaW5nIApgYGB7cn0KYmluZF9yb3dzKG5ldy5nZnBMaXZlQ2VsbHMpJT4lCiAgIyBmaWx0ZXIoZmllbGQgJWluJSBjKCJzNyIsInM4IikpICU+JSAKICBnZ3Bsb3QoLixhZXModGltZXBvaW50LCBnZnAubWVhbi5iZy5zdWIsIGdyb3VwID0gdW5pcXVlLnRyYWNrSUQgLGNvbG9yID0gc2FtcGxlKSkrCiAgZ2VvbV9saW5lKGFscGhhID0gMC4yKSsKICBmYWNldF93cmFwKH5maWVsZCwgc2NhbGVzID0gImZyZWVfeSIpCiMgZ2dzYXZlKGZpbGVuYW1lPSJsbi1tcmdfdnNfZ2ZwLnBuZyIsIHBsb3Q9IGxhc3RfcGxvdCgpICwgcGF0aCA9ICJ+L3Bsb3RzLzctMi0yMC9wbG90c190aGVzaXNfY29tX21lZXQtMjAyMC8iICwgd2lkdGggPSAxMyAsIGhlaWdodCA9IDgsIGJnID0gInRyYW5zcGFyZW50IikKCm5ldy5nZnBMaXZlQ2VsbHMgJT4lIAogIGdncGxvdCguLGFlcyhyZWFsLnRpbWUuZ2ZwLCBnZnAubWVhbi5iZy5zdWIsIGdyb3VwID0gdW5pcXVlLnRyYWNrSUQgLGNvbG9yID0gc2FtcGxlKSkrCiAgZ2VvbV9saW5lKGFscGhhID0gMC4yKSsKICBmYWNldF93cmFwKH5maWVsZCwgc2NhbGVzID0gImZyZWVfeSIpCiAgIyBhbm5vdGF0aW9uX2xvZ3RpY2tzKCkKYGBgCkZpeCBiYWNrZ3JvdW5kIGZvciBzMSBhbmQgczg6IGZpeGVkIGJhY2tncm91bmQgaW50ZW5zaXRpZXMgb2YgczEsIHMzLCA0IHRpbGwgczguIAoKI0ZpbHRlcmluZyBjZWxscyBiYXNlZCBvbiBhdXRvZmx1b3Jlc2NlbmNlIAoKIyNnZXR0aW5nIHRoZSBhdXRvZmx1b3Jlc2NlbmNlIHRocmVzaG9sZCBmb3IgZ2ZwIGFuZCBtY2hlcnJ5IApgYGB7cn0KYmluZF9yb3dzKG5ldy5nZnBMaXZlQ2VsbHMpICU+JSAKICBmaWx0ZXIoZXhwZXJpbWVudCA9PSAiMjBtaW4iKSAlPiUgCiAgZ2dwbG90KC4sYWVzKHggPSBnZnAubWVhbi5iZy5zdWIsIGNvbG9yID0gc2FtcGxlKSkrCiAgZ2VvbV9kZW5zaXR5KGFlcyh5ID0gLi5zY2FsZWQuLikpKwogIGZhY2V0X3dyYXAofnRpbWVwb2ludCAsIHNjYWxlcyA9ICJmcmVlX3giKSsKICBzY2FsZV94X2xvZzEwKCkKCmxpdmVDZWxsc1JGUC5EQVBJLkdGUCAlPiUgCiAgZmlsdGVyKHRpbWVwb2ludCA9PSAzMSkgJT4lIAogICMgZmlsdGVyKGV4cGVyaW1lbnQgPT0gIjIwbWluIikgJT4lIAogIGdncGxvdCguLGFlcyh4ID0gZ2ZwLm1lYW4uYmcuc3ViLCBjb2xvciA9IHNhbXBsZSkpKwogIGdlb21fZGVuc2l0eShhZXMoeSA9IC4uc2NhbGVkLi4pKSsKICBmYWNldF93cmFwKH5leHBlcmltZW50ICwgc2NhbGVzID0gImZyZWVfeCIpKwogIHNjYWxlX3hfbG9nMTAoKQoKbGl2ZUNlbGxzUkZQLkRBUEkuR0ZQICU+JSAKICBmaWx0ZXIodGltZXBvaW50ID09IDEpICU+JSAKICAjIGZpbHRlcihleHBlcmltZW50ID09ICIyMG1pbiIpICU+JSAKICBnZ3Bsb3QoLixhZXMoeCA9IGdmcC5tZWFuLmJnLnN1YiwgeSA9IGRhcGkubWVhbi5iZy5zdWIgLCBjb2xvciA9IGZpZWxkKSkrCiAgZ2VvbV9wb2ludCgpKwogIGZhY2V0X3dyYXAofmV4cGVyaW1lbnQgLCBzY2FsZXMgPSAiZnJlZV94IikKCmBgYAoKCgpgYGB7cn0KI0dldHRpbmcgdGhlIGdmcCB0aHJlc2hvbGQgZm9yIGZpbHRlcmluZyBjZWxscyBiZWxvdyB0aGlzIHRocmVzaG9sZCBzZXQgdXAgYmFzZWQgb24gYWxsIHRoZSAzMSB0aW1lIHBvaW50cyBmb3IgdGhlIG1yZyBjZWxscyAKZ2ZwLm1pbi5pbnQgPC0gZ2ZwLnRoZXJzaG9sZC4zMXRwKAogIGxpc3Qub2YuZmlsZXMuYmcuc3ViLmFib3ZlLjAgPSBuZXcuZ2ZwTGl2ZUNlbGxzICU+JSAKICAgIHNwbGl0KC4kZXhwZXJpbWVudCkpCgoKI0dldHRpbmcgdGhlIG1jaGVycnkgdGhyZXNob2xkIGZvciBmaWx0ZXJpbmcgY2VsbHMgYmVsb3cgdGhpcyB0aHJlc2hvbGQgc2V0IHVwIGJhc2VkIG9uIGFsbCB0aGUgMzEgdGltZSBwb2ludHMgZm9yIHRoZSBtcmcgY2VsbHMgCnJmcC5taW4uaW50IDwtIHJmcC50aGVyc2hvbGQuMzF0cC50ZW1wKGxpc3Qub2YuZmlsZXMuYmcuc3ViLmFib3ZlLjAgPSBsaXZlQ2VsbHNSRlAuREFQSS5HRlAgKQoKcmZwLm1pbi5pbnQgPC0gcmZwLm1pbi5pbnQgJT4lIG11dGF0ZShwdXAxX3RocmVzaG9sZCA9IDIwKQoKCmBgYAoKI2ZpbHRlcmluZyBiYXNlZCBvbiBwdXAxLXJmcCBleHByZXNzaW9uIAojI2ZpbHRlcmluZyBjZWxscyB3aGljaCBhcmUgYWJvdmUgdGhlIGdmcCBhbmQgcmZwIHRocmVzaG9sZCAKSW4gdGhlIGZpbHRlci5jZWxscy5iZWxvdy5hdXRvZmx1b3IuMzF0cC5nZnBWMigpIGZ1bmN0aW9uLCB0aGUgZnVuY3Rpb24gbG9va3MgZm9yIHRoZSBjb2x1bW4gbmFtZWQgInRocmVzaG9sZCIgYW5kIEkgbmVlZCB0byBkZWNpZGUgd2hpY2ggY29sdW1uIHdpbGwgYmUgdGhyZXNob2xkIGJhc2VkIG9uIHRoZSBvdmVybGFwIG9mIHRoZSBuZWcgYW5kIHBvc2l0aXZlIGNlbGxzLiBUaGlzIGlzIGJlY2F1c2UgdGhlcmUgYXJlIGNlbGxzIHdoaWNoIGJlY29tZSBkZWFkL2JlY29tZSBpbiBmb2N1cyBhcyB5b3Uga2VlcCB0YWtpbmcgaW1hZ2VzIHdoaWNoIG1pZ2h0IHN1ZGRlbmx5IGluY3JlYXNlIHRoZSA5NXRoIHF1YW50aWxlIGludGVuc2l0eSBvZiB0aGUgbmVnYXRpdmUgY2VsbHMuIApgYGB7cn0KI2dldCBhIGZpbHRlcmVkIGRmIG9mIGNlbGxzIHBhc3NpbmcgdGhlIGdmcCB0aHJlc2hvbGQgc2V0IGFib3ZlIAojdGhpcyBmdW5jdGlvbiBiZWxvdyBmaXJzdCByZW1vdmVzIGNlbGxzIHdpdGggcHVwMS1yZnAgbGVzcyB0aGFuIHRoZSB0aHJlc2hvbGQgc2V0LiAKI1RoZW4gaXQgcmVtb3ZlcyB0aGUgY2VsbHMgd2l0aCBsZXNzIHRoYW4gQUYgdGhyZXNob2xkIHNldCBhdCB0cCA9MSAKI0FmdGVyIHRoYXQgaXQgc3VidHJhY3RzIHRoZSBhZiB2YWx1ZSBmcm9tIGV2ZXJ5IGNlbGwgZm9yIGV2ZXJ5IHRpbWVwb2ludCwgYW5kIGlmIHRoZSBzdWJ0cmFjdGVkIHZhbHVlIGlzIGxlc3MgdGhhbiAxIGl0IG1ha2VzIGl0IE5BLiAKCmNlbGxzLmZpbHRlcmVkLmRmLjMxdHAgPC0gZmlsdGVyLmNlbGxzLmJlbG93LmF1dG9mbHVvci4zMXRwLmdmcFYyKAogIGRmX3JmcF9kYXBpX2dmcCA9IGxpdmVDZWxsc1JGUC5EQVBJLkdGUCwKICAKICByZnBfbWluX2ludCA9IHJmcC5taW4uaW50ICU+JSByZW5hbWUoInF1YW50Xzk1IiA9ICJ0aHJlc2hvbGRfOTUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInRocmVzaG9sZF85NSIgPSAicHVwMV90aHJlc2hvbGQiKSwKICAKICBnZnBfbGl2ZV9jZWxsc19saXN0ID0gbmV3LmdmcExpdmVDZWxscyAlPiUgc3BsaXQoLiRleHBlcmltZW50KSwKICAKICBnZnBfbWluX2ludCA9IGdmcC5taW4uaW50ICU+JSAKICAgIG11dGF0ZSh0aHJlc2hvbGQgPSB0aHJlc2hvbGRfOTUgKQopCgpmaWx0ZXJlZC5kZi5uZXcud28uYWYuMzF0cCA8LSBjZWxscy5maWx0ZXJlZC5kZi4zMXRwJGZpbHRlcmVkLmRmLm5ldyAlPiUgCiAgYmluZF9yb3dzKCkgJT4lIAogIGZpbHRlcihzYW1wbGUgPT0gInBvcy5zaWduYWwiKSAlPiUgCiAgc3BsaXQoLiRleHBlcmltZW50KQoKdW5pcXVlKGZpbHRlcmVkLmRmLm5ldy53by5hZi4zMXRwJGAyMG1pbmAkdGltZXBvaW50KQoKICAKYGBgCgpyZW1vdmUgdGhlIGZpcnN0IHR3byBibHVycnkgaW1hZ2VzIGZyb20gczcKYGBge3J9CiMgZmlsdGVyZWQuZGYubmV3LndvLmFmLjMxdHAkYDIwbWluYCA8LSBmaWx0ZXJlZC5kZi5uZXcud28uYWYuMzF0cCRgMjBtaW5gICU+JSBmaWx0ZXIoZmllbGQgPT0gInM3IikKIyAgIGZpbHRlcighKGZpZWxkID09ICJzNyIgJiB0aW1lcG9pbnQgJWluJSBjKDEsMikpKSAKCmBgYAoKCiNtYWtpbmcgZGYgZm9yIGJ1bGsgcmVncmVzc2lvbgpgYGB7cn0KIyMjVGhpcyBmdW5jdGlvbiBjcmVhdHMgdGhlIGRmIGZvciBmaXR0aW5nIHRoZSAyNCBtb2RlbHMgCiMgbGlzdC5kZi5tb2RlbCA8LSBkZi5tb2RlbChmaWx0ZXJlZC5kZi5uZXcgPSBmaWx0ZXJlZC5kZi5uZXcud28uYWYpCmRmLm1vZGVsLjMxdHAuZ2ZwIDwtIGRmLm1vZGVsLmdmcChmaWx0ZXJlZC5kZi5uZXcgPSBmaWx0ZXJlZC5kZi5uZXcud28uYWYuMzF0cCkKZGYubW9kZWwuMzF0cC5nZnAKCiMjIyNUaGlzIGZ1bmN0aW9uIGNsZWFucyB1cCB0aGUgZGYgd2hlcmUgeW91IHN1YnRyYWN0IHRoZSB0PTAgaW50ZW5zaXR5IHdpdGggYWxsIHRoZSBvdGhlciBpbnRlbnNpdGllcyBmb3IgZ2ZwCmZpbmFsLmRhdGEuMzF0cC5nZnAgPC0gY2xlYW4uZGYubW9kZWxpbmcuZ2ZwKGRhdGEuZ2ZwID0gZGYubW9kZWwuMzF0cC5nZnApCgpgYGAKCgpPbiAxLzI4LzIxIHRhbGtlZCB0byBwcmVtYWwgYWJvdXQgZmlsdGVyaW5nOiAKMS4gUmVtb3ZlIGNlbGxzIHdoaWNoIGhhdmUgcG9zaXRpdmUgZGVsdGEgSW50ZW5zaXR5IG1vcmUgdGhhbiAyIHRpbWVzIApgYGB7cn0KI2dldHRpbmcgSURzIG9mIGNlbGxzIHdoaWNoIGhhdmUgcG9zaXRpdmUgaW50ZW5zaXR5IHZhbHVlcyBmb3IgbGVzcyB0aGFuIDIgdGltZXBvaW50cyAKaWRzLmludC4yIDwtIGZpbmFsLmRhdGEuMzF0cC5nZnAgJT4lIAogIGdyb3VwX2J5KHVuaXF1ZS50cmFja0lEKSAlPiUgCiAgdGFsbHkobG4uZ2ZwLmRpZiA+IDApICU+JSAKICBmaWx0ZXIobjwyKSAlPiUgICAgICAgICAgICAja2VlcCBjZWxscyB3aGljaCBoYXZlIGxlc3MgdGhhbiB0d28gcG9zaXRpdmUgaW50ZW5zaXR5IHZhbHVlcwogIHB1bGwodW5pcXVlLnRyYWNrSUQpCgojZmlsdGVyaW5nIGNlbGxzIHdoaWNoIGhhdmUgdHJhY2tJRCBpbiB0aGUgYWJvdmUgdmVjdG9yICAKI2dmcAp0ZW1wLnBvc0ludEJsdzIuZ2ZwIDwtIGZpbmFsLmRhdGEuMzF0cC5nZnAgJT4lIAogIGZpbHRlcih1bmlxdWUudHJhY2tJRCAlaW4lIGlkcy5pbnQuMikgCgpkZl9mb3JfTWVjaGFuaXN0aWNNb2RlbCA8LSB0ZW1wLnBvc0ludEJsdzIuZ2ZwICAlPiUKICBsZWZ0X2pvaW4oCiAgICAuLAogICAgYmluZF9yb3dzKGZpbHRlcmVkLmRmLm5ldy53by5hZi4zMXRwKSAsCiAgICBieSA9IGMoCiAgICAgICJ1bmlxdWUudHJhY2tJRCIsCiAgICAgICJ0aW1lcG9pbnQiICwKICAgICAgImV4cGVyaW1lbnQiICwKICAgICAgImdmcC5tZWFuLmJnLmFmLnN1Yi5uZXciICwKICAgICAgImV4cC5maWVsZCIKICAgICkKICApCgojc2F2ZSB0aGlzIGRhdGFmcmFtZSBmb3IgaGFsZiBsaWZlIGVzdGltYXRpb24KCmBgYAoKCgpgYGB7cn0KY2VsbF9hdHJpYnV0ZXNfZmluYWwgPC0gZGZfZm9yX01lY2hhbmlzdGljTW9kZWwgJT4lIAogIGZpbHRlcih0aW1lcG9pbnQgPT0gMSkgICU+JSAKICBsZWZ0X2pvaW4oLixsaXZlQ2VsbHNSRlAuREFQSS5HRlAgJT4lIHNlbGVjdCh1bmlxdWUudHJhY2tJRCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aW1lcG9pbnQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhwLmZpZWxkLGV4cGVyaW1lbnQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmZwLm1lYW4uYmcuc3ViLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJmcC5tZWFuLmJnLnN1Yi5wdW5jdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGFwaS5tZWFuLmJnLnN1YiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXBpLm1lYW4uYmcuc3ViLnB1bmN0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZnAuc3VtLmJnLnN1YiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZnAuc3VtLmJnLnN1Yi5wdW5jdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGFwaS5zdW0uYmcuc3ViLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhcGkuc3VtLmJnLnN1Yi5wdW5jdGEpLCAKICAgICAgICAgICAgYnkgPSBjKCJ1bmlxdWUudHJhY2tJRCIsICJ0aW1lcG9pbnQiLCAiZXhwLmZpZWxkIiwgImV4cGVyaW1lbnQiKSkgCgpjZWxsX2F0cmlidXRlc19maW5hbCAlPiUgZ3JvdXBfYnkoZXhwLmZpZWxkKSAlPiUgdGFsbHkoKQoKd3JpdGVfY3N2KGNlbGxfYXRyaWJ1dGVzX2ZpbmFsLGZpbGUgPSAiL2hvbWUvRGFzL3Bsb3RzL3B1cDEtcmZwLWdmcC1kZWNheS83LTIwLTIyLXN0YWJsZS1nZnAvZGF0YS83LTIwLTIyX3N0YWJsZV9wdXAxX2F0dHJpYnV0ZXMuY3N2IikKICAKCmBgYAoKI3NhdmluZyB0aGUgZGF0YSAKYGBge3J9CmdmcF9jbG4yUGVzdF9maWx0ZXJlZCA8LSBkZl9mb3JfTWVjaGFuaXN0aWNNb2RlbCAgJT4lCiAgcmVuYW1lKCJjZWxsLmlkIiA9ICJ1bmlxdWUudHJhY2tJRCIsCiAgICAgICAgICJnZnBTdW1CZ0FGc3ViIiA9ICJnZnAuc3VtLmJnLmFmLnN1YiIsCiAgICAgICAgICJnZnBNZWFuQmdBRnN1YiI9ImdmcC5tZWFuLmJnLmFmLnN1Yi5uZXciLAogICAgICAgICAibmF0LmxvZy5HZnBNZWFuIiA9ICJsbi5nZnAiICwgCiAgICAgICAgICJkZWx0YS5pbnQiID0gImxuLmdmcC5kaWYiLAogICAgICAgICAiZGVsdGEudGltZSIgPSAidGltZSIKICAgICAgICAgKSAlPiUgCiAgc2VsZWN0KCBjZWxsLmlkLAogICAgICAgICBnZnBTdW1CZ0FGc3ViLAogICAgICAgICBnZnBNZWFuQmdBRnN1YiwKICAgICAgICAgbmF0LmxvZy5HZnBNZWFuLAogICAgICAgICBkZWx0YS50aW1lLAogICAgICAgICBpbWFnZS5ubywKICAgICAgICAgZGVsdGEuaW50LCAKICAgICAgICAgZXhwLmZpZWxkCiAgICAgICAgICkKCndyaXRlX2NzdihnZnBfY2xuMlBlc3RfZmlsdGVyZWQgLCBmaWxlID0gIn4vcGxvdHMvcHVwMS1yZnAtZ2ZwLWRlY2F5LzctMjAtMjItc3RhYmxlLWdmcC9kYXRhL2dmcF9zdGFibGVfcHVwMV9maWx0ZXJlZC5jc3YiKQpgYGAKCiNTQVZJTkcgVEhFIERBVEFGUkFNRSBXSElDSCBIQVMgQUxMIFRIRSBCQUNLR1JPVU5EIElOVCwgQVVUT0ZMVU9SIElOVEVOU0lUWSAoQVQgVEhFIElOVEVSU0VDVElPTiwgVEhFIDgwVEggQU5EIFRIRSA5NVRIIFFVQU5USUxFIE9GIE1SRyBBVVRPIEdGUCBJTlRFTlNJVFkpCgpgYGB7cn0Kd3JpdGVfY3N2KGRmX2Zvcl9NZWNoYW5pc3RpY01vZGVsICwgZmlsZSA9ICJ+L3Bsb3RzL3B1cDEtcmZwLWdmcC1kZWNheS83LTIwLTIyLXN0YWJsZS1nZnAvZGF0YS9nZnBfc3RhYmxlX3B1cDFfcmF3X2RhdGEuY3N2IikKYGBgCgpgYGB7cn0KZ2ZwX2NsbjJQZXN0X2ZpbHRlcmVkICU+JSAKICBnZ3Bsb3QoLixhZXMoZGVsdGEudGltZSwgZ2ZwTWVhbkJnQUZzdWIsIGdyb3VwID0gY2VsbC5pZCkpKwogIGdlb21fbGluZShhbHBoYSA9IDAuMikrCiAgZmFjZXRfd3JhcCh+ZXhwLmZpZWxkLCBzY2FsZXMgPSAiZnJlZV95IikKCmBgYAoK